///<reference path="../typings/knockout.d.ts" />
import mediator = require('index.mediator');

var idCtr = 0;

export class Model {
	public id: number = idCtr++;
	public user = ko.observable('anonymous');
	
	public kk = ko.observable<Konsenskiste>();
	
	public topicBreadcrumb = ko.observableArray<Topic>([new Topic(null)]);
	public topic = ko.computed<Topic>(() => this.topicBreadcrumb()[this.topicBreadcrumb().length-1]);
	
	public selectChildTopic(child: Topic) {
		this.topicBreadcrumb.push(child);
	}
	
	public selectBreadcrumbTopic(parent: Topic) {
		var i = this.topicBreadcrumb.indexOf(parent);
		if(i != -1)
			this.topicBreadcrumb.splice(i + 1);
	}
	
	public selectTopic(topic: Topic, role: TopicRole) {
		switch(role) {
			case TopicRole.Child:
				this.selectChildTopic(topic);
				break;
			case TopicRole.Breadcrumb:
				this.selectBreadcrumbTopic(topic);
				break;
		}
	}
	
	private mtr: mediator.Mediator;
	
	constructor(mtr: mediator.Mediator) {
		this.mtr = mtr;
		mtr.setAuthDataFunction(() => ({ user: this.user(), password: 'none' }));
	}
}

export enum TopicRole { Breadcrumb, Child }

export interface QkElement {
	id: number;
	type: string;
	
	title: KnockoutObservable<string>;
	text: KnockoutObservable<string>;
	
	rating: KnockoutObservable<string>;
	likeRating: KnockoutComputed<string>;
	stronglikeSum: KnockoutObservable<number>;
	likeSum: KnockoutObservable<number>;
	neutralSum: KnockoutObservable<number>;
	dislikeSum: KnockoutObservable<number>;
	strongdislikeSum: KnockoutObservable<number>;
}

export interface QkComment extends QkElement { parent: KnockoutObservable<QkCommentable> }

export interface QkWithContext extends QkElement {
	context: KnockoutObservable<string>;
}

export interface QkChild extends QkElement {
	parent: KnockoutObservable<QkParent>;
}

export interface QkParent extends QkElement {
	children: KnockoutObservableArray<Kernaussage>;
}

export interface QkCommentable extends QkElement {
	comments: KnockoutObservableArray<QkComment>;
}

export interface QkMainElement extends QkElement, QkCommentable, QkWithContext {}

export class QkElementBase implements QkElement {
	public id: number;
	public type = 'none';
	
	public title = ko.observable<string>();
	public text = ko.observable<string>();
	
	public rating = ko.observable<string>('like');
	public likeRating = ko.computed<string>({
		read: () => {
			switch(this.rating()) {
				case 'like': case 'stronglike':
					return 'like';
				case 'dislike': case 'strongdislike':
					return 'dislike';
				default:
					return 'none';
			}
		},
		write: (val: boolean) => {
			alert('not implemented');
		}
	});
	public stronglikeSum = ko.observable<number>();
	public likeSum = ko.observable<number>();
	public neutralSum = ko.observable<number>();
	public dislikeSum = ko.observable<number>();
	public strongdislikeSum = ko.observable<number>();
	
	constructor(id: number) {
		this.id = id;
	}
}

export class QkMainElementBase extends QkElementBase implements QkMainElement {
	public comments = ko.observableArray<QkComment>();
	public context = ko.observable<string>();
	
	constructor(id: number) {
		super(id);
	}
}

export interface Konsenskiste extends QkMainElement, QkParent {}
export class KonsenskisteImpl extends QkMainElementBase implements Konsenskiste {
	public children = ko.observableArray<Kernaussage>();

	constructor(id?: number) {
		super(id);
		this.type = 'kk';
	}
}

export interface Kernaussage extends QkMainElement, QkParent, QkChild, QkWithContext {
	parent: KnockoutObservable<Konsenskiste>;
}

export class KernaussageImpl extends QkMainElementBase implements Kernaussage {
	public parent = ko.observable<Konsenskiste>();
	public children = ko.observableArray<Kernaussage>();
	
	public context = ko.observable<string>();
	
	constructor(id?: number, parent?: Konsenskiste) {
		super(id);
		this.type = 'ka';
		
		this.parent(parent);
	}
}

export class Kommentar extends QkElementBase implements QkComment {
	public parent = ko.observable<QkCommentable>();

	constructor(id?: number, parent?: QkCommentable) {
		super(id);
		this.type = 'cmt';
		
		this.parent(parent);
	}
}

export class Topic {
	public id: number;
	
	public parent = ko.observable<Topic>();
	public children = ko.observableArray<Topic>();
	public kks = ko.observableArray<Konsenskiste>();
	
	public title = ko.observable<string>();
	public text = ko.observable<string>();
	
	constructor(id?: number, parent?: Topic) {
		this.id = id;
		this.parent(parent);
	}
}